﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bankeren.Engine.Cards;
using System.Runtime.CompilerServices;
using System.Threading;

namespace Bankeren.Engine
{
    internal class Trick
    {
        #region Fields

        private Round round;
        private int lead;
        private int trickNumber;
        private Suit followSuit;
        private Dictionary<Player, Card> cards;

        #endregion

        #region Ctor

        public Trick(Round round, int lead, int trickNumber)
        {
            this.round = round;
            this.lead = lead;
            this.trickNumber = trickNumber;
            this.cards = new Dictionary<Player, Card>();
        }

        #endregion

        #region Methods

        #region Private Methods

        private int DetermineWinner()
        {
            Suit trump = round.Trump.Suit;
            int winner = lead;
            for (int i = 0, seat = (lead + 1) % Game.MAXPLAYERS; i < Game.MAXPLAYERS; i++)
            {
                Card winnerCard = cards[round.Game.Players[winner]];
                Card seatCard = cards[round.Game.Players[seat]];
                // Startet med trumf
                if (winnerCard.Suit == trump)
                {
                    // Hvis neste kort er trumf OG større, nytt vinnerkort
                    if (seatCard.Suit == trump && seatCard.Rank.CompareTo(winnerCard.Rank) > 0)
                        winner = seat;
                }
                else
                {
                    if (seatCard.Suit == trump)
                    {
                        winner = seat;
                    }
                    else if (seatCard.Suit == winnerCard.Suit && seatCard.Rank.CompareTo(winnerCard.Rank) > 0)
                    {
                        winner = seat;
                    }
                }
                seat = ++seat % Game.MAXPLAYERS;
            }
            return winner;
        }

        private bool ValidCard(Card card)
        {
            // TODO: Implement this
            return true;
        }

        private void Log(string format, params object[] args)
        {
            round.Log("Trick " + trickNumber + ": " + format, args);
        }

        #endregion

        #region Internal Methods

        internal int PlayTrick()
        {
            Log(string.Format("Starting. Lead: {0}", round.Game.Players[lead]));
            // Notify of trick number
            foreach (Player player in round.Game.Players.Values)
                player.TrickStarted(this.trickNumber);
            for (int i = 0, currentSeat = lead; i < Game.MAXPLAYERS; i++)
            {
                foreach (Player player in round.Game.Players.Values)
                    player.Turn(currentSeat, followSuit);
                // Wait for card to be placed
                while (!cards.ContainsKey(round.Game.Players[currentSeat]))
                    Thread.Sleep(10);
                currentSeat = ++currentSeat % Game.MAXPLAYERS;
            }
            int winner = DetermineWinner();
            Log(string.Format("Finished. Winner: {0}", round.Game.Players[winner]));
            foreach (Player player in round.Game.Players.Values)
                player.TrickEnded(winner);
            //Thread.Sleep(2000);
            return winner;
        }

        internal bool PlayCard(Player player, Card card)
        {
            if (ValidCard(card))
            {
                this.cards.Add(player, card);
                // If it's the leading card, set followSuit
                if (player.Equals(round.Game.Players[lead]))
                    followSuit = card.Suit;
                foreach (Player p in round.Game.Players.Values)
                    p.CardPlayed(player.Seat, card);
                Log(string.Format("Card from {0}: {1}", player, card));
                return true;
            }
            else
                return false;
        }

        #endregion

        #endregion
    }
}
